package com.demo.decorator06.example01;

/**
 * 其实就是进房子找衣服，通过装饰者的三层装饰，把细节变得丰富，该Demo的关键点：
 *
 * （1）Decorator 抽象类持有Human接口，方法全部委托给该接口调用，目的是交给该接口的实现类进行调用。
 *
 * （2）Decorator 抽象类的子类，即具体装饰者，里面都有一个构造方法调用 super(human)，这里就体现了抽象类依赖于子类实现，
 * 即抽象依赖于实现的原则。因为构造函数的参数都是 Human 类型，只要是该 Human 的实现类都可以传递进去，即表现出
 * Decorator dt = new Decorator_second(new Decorator_first(new Decorator_zero(human))) 这种结构的样子，
 * 所以当调用 dt.wearClothes() 的时候，又因为每个具体装饰者类中，都先调用 super.wearClothes() 方法，
 * 而该 super已经由构造函数传递并指向了具体的某一个装饰者类，
 * 那么最终调用的就是装饰类的方法，然后才调用自身的装饰方法，即表现出一种
 * 装饰、链式的类似于过滤的行为。
 *
 * （3）具体被装饰者类，可以定义初始的状态或者初始的自己的装饰，后面的装饰行为都在此基础上一步一步进行点缀、装饰。
 *
 * （4）装饰者模式的设计原则为：对扩展开放、对修改关闭，这句话体现在如果想扩展被装饰者类的行为，无须修改装饰者抽象类，
 * 只需继承装饰者抽象类，实现额外的一些装饰或者叫行为即可对被装饰者进行包装。所以：扩展体现在继承、修改体现在子类中，
 * 而不是具体的抽象类，这充分体现了依赖倒置原则，这是自己理解的装饰者模式。
 */

//定义被装饰者
interface Human
{
    void wearClothes();
}
 
//定义装饰者
abstract class Decorator implements Human
{
    private final Human human;
 
    public Decorator(Human human)
    {
        this.human = human;
    }
 
    @Override
    public void wearClothes()
    {
        human.wearClothes();
    }
}
 
//下面定义三种装饰，这是第一个，第二个第三个功能依次细化，即装饰者的功能越来越多
class Decorator_zero extends Decorator {
 
    public Decorator_zero(Human human) {
        super(human);
    }
 
    public void goHome() {
        System.out.println("进房子。。");
    }
 
    @Override
    public void wearClothes() {
        super.wearClothes();
        goHome();
    }
}
 
class Decorator_first extends Decorator {
 
    public Decorator_first(Human human) {
        super(human);
    }
 
    public void goClothespress() {
        System.out.println("去衣柜找找看。。");
    }
 
    @Override
    public void wearClothes() {
        super.wearClothes();
        goClothespress();
    }
}
 
class Decorator_two extends Decorator {
 
    public Decorator_two(Human human) {
        super(human);
    }
 
    public void findClothes() {
        System.out.println("找到一件D&G。。");
    }
 
    @Override
    public void wearClothes() {
        super.wearClothes();
        findClothes();
    }
}
 
 
class Person implements Human {
 
    @Override
    public void wearClothes() {
        System.out.println("穿什么呢。。");
    }
}
 
//测试类
public class DecoratorTest
{
    public static void main(String[] args)
    {
        Human person = new Person();
        Decorator decorator = new Decorator_two(new Decorator_first(new Decorator_zero(person)));
        decorator.wearClothes();
    }
}